﻿using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.Extensions.DependencyModel;
using Mysoft.Common.Configuration;
using Mysoft.Common.Const;
using Mysoft.Common.Extensions;
using Mysoft.Entity;
using Mysoft.Entity.Basic;
using System.Reflection;
using System.Runtime.Loader;
using System.Text;

namespace Mysoft.Data.DBContext
{
    public class EfDbContext : DbContext
    {
        public EfDbContext(DbContextOptions<EfDbContext> options)
         : base(options)
        {

        }
        /// <summary>
        /// 设置跟踪状态
        /// </summary>
        public bool QueryTracking
        {
            set
            {
                this.ChangeTracker.QueryTrackingBehavior =
                       value ? QueryTrackingBehavior.TrackAll
                       : QueryTrackingBehavior.NoTracking;
            }
        }
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            string connectionstring = AppSetting.DbConnectionString;
            string dbtype = AppSetting.DBType;
            if (dbtype == DBType.MySql)
            {
                optionsBuilder.UseMySql(connectionstring, new MySqlServerVersion(new Version()));
            }
            else if (dbtype == DBType.PgSql)
            {

                //optionsBuilder.UseNpgSql(connectionstring);
            }
            else
            {
                optionsBuilder.UseSqlServer(connectionstring);
            }

            //默认禁用实体跟踪
            //optionsBuilder = optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
            base.OnConfiguring(optionsBuilder);
        }
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            try
            {
                var cc = DependencyContext.Default.CompileLibraries.Count();
                //获取所有类库
                var compilationLibrary = DependencyContext
                    .Default
                    .CompileLibraries
                    .Where(x => !x.Serviceable && x.Type != "package" && x.Type == "project");
                foreach (var _compilation in compilationLibrary)
                {
                    //加载指定类
                    AssemblyLoadContext.Default
                    .LoadFromAssemblyName(new AssemblyName(_compilation.Name))
                    .GetTypes()
                    .Where(x =>
                        x.GetTypeInfo().BaseType != null
                        && x.BaseType == (typeof(EntityBase)))
                        .ToList().ForEach(t =>
                        {
                            modelBuilder.Entity(t);
                        });
                }
                base.OnModelCreating(modelBuilder);

                if (!Directory.Exists("/var/www/log"))//如果不存在就创建file文件夹
                    Directory.CreateDirectory("/var/www/log");

                using (FileStream stream = File.Open("/var/www/log/logtry.txt", FileMode.OpenOrCreate, FileAccess.Write))
                {
                    byte[] by = Encoding.Default.GetBytes(cc.ToString());
                    stream.SetLength(0);
                    stream.Write(by, 0, by.Length);
                }
            }
            catch (Exception ex)
            {

                //string mapPath = ($"Log/").MapPath();
                //Utilities.FileHelper.WriteFile(mapPath,
                //    $"syslog_{DateTime.Now.ToString("yyyyMMddHHmmss")}.txt",
                //    type?.Name + "--------" + ex.Message + ex.StackTrace + ex.Source);
                if (!Directory.Exists("/var/www/log"))//如果不存在就创建file文件夹
                    Directory.CreateDirectory("/var/www/log");

                using (FileStream stream = File.Open("/var/www/log/logcatch.txt", FileMode.OpenOrCreate, FileAccess.Write))
                {
                    byte[] by = Encoding.Default.GetBytes(ex.Message);
                    stream.SetLength(0);
                    stream.Write(by, 0, by.Length);
                }
            }
        }
    }
    public static class EfDbContextExtensions
    {
        public static void EnsureSeedData(this EfDbContext context)
        {
            if (context.AllMigrationsApplied())
            {
                var user = context.Set<Sys_User>();
                if (!user.Any())
                {
                    Guid operateid = new Guid("D3FB5087-9BC3-4233-AAAC-C05E2D52AC38");
                    string operatename = "超级管理员";
                    DateTime operatdate = DateTime.Now;
                    user.AddRange(new Sys_User { Id = operateid, CreateGuid = operateid, UpdateGuid= operateid, CreateName = operatename,UpdateName= operatename,CreateDate = operatdate,UpdateDate= operatdate,  Name = operatename, Code = "admin", Password = "!1qaz7410.", });
                    context.SaveChanges();
                }
            }
        }
    }
    public static class DbContextExtensions
    {
        public static bool AllMigrationsApplied(this DbContext context)
        {
            var applied = context.GetService<IHistoryRepository>()
                .GetAppliedMigrations()
                .Select(m => m.MigrationId);

            var total = context.GetService<IMigrationsAssembly>()
                .Migrations
                .Select(m => m.Key);

            return !total.Except(applied).Any();
        }
    }
}
